package org.nf.users.utils;

import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

/**
 * JWT工具类
 */
public class JWTUtil {

    /**
     * 密钥
     */
    private static final Key KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    /**
     * 签发人
     */
    private static final String ISS = "edu.nf";

    /**
     * 主题
     */
    private static final String SUBJECT = "JWT_AUTH";


    /**
     * 创建 Jwt 令牌字符串（Token）
     *
     * @param claims 签署内容
     * @param ttl    设置过期时间，单位毫秒 - 一天：1 * 24 * 60 * 60 * 1000
     * @return 令牌字符串
     */
    public static String createToken(Map<String, Object> claims, long ttl) {
        return Jwts.builder()
                // 签名 - 通过KEY定义的HS256的算法进行加密
                .signWith(KEY)
                // 设置签发人
                .setIssuer(ISS)
                // 设置主题
                .setSubject(SUBJECT)
                // 设置数据内容
                .setClaims(claims)
                // 设置签发时间
                .setIssuedAt(new Date())
                // 设置过期时间
                .setExpiration(setExpDate(ttl))
                // 设置jwt唯一标识
                .setId(UUID.randomUUID().toString())
                // 创建 jwt 令牌字符串
                .compact();
    }


    /**
     * 设置过期时间
     *
     * @param ttl
     * @return
     */
    private static Date setExpDate(long ttl) {
        return new Date(System.currentTimeMillis() + ttl);
    }

    /**
     * 验证令牌字符串的有效性，如果验证不通过则抛出相应的异常
     *
     * @param token 令牌
     */
    public static void verify(String token) {
        try {
            Jwts.parserBuilder()
                    // 设置签名密钥 - 通过 KEY 定义的HS256的算法进行解密
                    .setSigningKey(KEY)
                    .build()
                    // 解析 token 中的数据载体部分
                    .parseClaimsJws(token);
        } catch (JwtException e) {
            throw new RuntimeException("验证令牌失败", e);
        }
    }

    /**
     * 获取 payload 的数据内容
     *
     * @param token 令牌字符串
     * @param name  key
     * @param type  key类型的class对象
     * @param <T>   key类型
     * @return value
     */
    public static <T> T getPayload(String token, String name, Class<T> type) {
        return Jwts.parserBuilder()
                // 设置签名密钥 - 通过 KEY 定义的HS256的算法进行解密
                .setSigningKey(KEY)
                .build()
                // 解析 token 中的数据载体部分
                .parseClaimsJws(token)
                // 获取载体数据
                .getBody()
                // 根据 name 和 type 获取对应的 value
                .get(name, type);
    }

}
